//-----------------------------------------------------------------------------
// TargetBL_Main.c
//-----------------------------------------------------------------------------
// Copyright (C) 2010 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// The main routine for the Target Bootloader Firmware.
//
// 
//
//
// Target:         C8051Fxxx (Any Silicon Labs Flash MCU)
// Tool chain:     Generic
// Command Line:   None
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "TargetBL_Config.h"
#include "TargetBL_Interface.h"
#include "UART_Interface.h"
#include "CRC.h"
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------

//------------------------------------------
// 异常应答代码
//------------------------------------------
#define ILLEGAL_FUNCTION            0x01
#define ILLEGAL_DATA_ADDRESS        0x02
#define ILLEGAL_DATA_VALUE          0x03
#define SERVER_DEVICE_FAILURE       0x04
#define ACKNOWLEDGE                 0x05
#define SERVER_DEVICE_BUSY          0x06
#define MEMORY_PARITY_ERROR         0x08
#define GATEWAY_PATH_UNAVAILABLE    0x0A
#define GATEWAY_TARGET_NO_RESPONSE  0x0B


//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
#ifdef BL_OVERRIDE_PIN
sbit BL_Override_Pin = BL_OVERRIDE_PIN;
#endif

extern const U8 code TGT_BL_InfoBlock[TGT_BL_FW_INFOBLOCK_LENGTH];

U8 xdata Page_Buf[TGT_FLASH_PAGE_SIZE];
U8 xdata rx_buf[TGT_BL_BUF_SIZE];
U8 data rx_len = 0;
U8 data server_address = 0;
U16 data uart_timestamp;
bit user_app_ready = 0;

#define APP_MODE        0
#define BOOTLOADER_MODE 1

// Bit masks for the RSTSRC SFR
#define PORSF  0x02
#define FERROR 0x40

//=============================================================================
// Function Definitions
//=============================================================================

void Response()
{
    // 计算CRC
    *(U16*)&rx_buf[rx_len] = Get_Buf_CRC(rx_buf, rx_len);
    rx_len += 2;

    // 如果时间距离接收超过10ms, 不要发送
    if (SystemTick() - uart_timestamp >= TEN_MS)
        return ;

    uart_send(rx_buf, rx_len);
}

void Exception_Response(U8 err)
{
    rx_buf[1] |= 0x80;
    rx_buf[2] = err;
    rx_len = 3;

    Response();
}

// 诊断
void Diagnose()
{
    U16 subfun = *(U16*)&rx_buf[2]; // 子功能代码

    switch(subfun)
    {
    case 0x00:      // 原样返回请求数据
    case 0x03:      // 改变ASCII结束符
        rx_len -= 2;
        Response();
        break;

    case 0x01:      // 复位通讯端口
        rx_len = 6;
        subfun = *(U16*)&rx_buf[4];
        Response();

        // 重启
        RSTSRC = 0x12; // Initiate software reset with vdd monitor enabled
        break;          // 运行不到此处

    default:        // 未实现或不正确的子功能代码
        Exception_Response(ILLEGAL_FUNCTION);
        break;
    }
}

//=============================================================================
// Main Routine
//=============================================================================
void main(void)
{
    U8 device_mode = BOOTLOADER_MODE;
    U16 data index;
    U16 data count;
    U8 xdata * data dst;
    U8 xdata * data src;
    U8 data n;
    U32 addr;

    //---------------------------------------
    // Check the bootloader consition.
    //---------------------------------------
   // The Signature (in Flash) should be valid to allow application FW execution.
   // This is written at the end of the bootloading process by the bootloader.
    if(FLASH_Read(APP_FW_SIG0_ADDR) == SIG_BYTE0 &&
            FLASH_Read(APP_FW_SIG0_ADDR-1) == SIG_BYTE1 &&
            FLASH_Read(APP_FW_SIG0_ADDR-2) == SIG_BYTE2 &&
            FLASH_Read(APP_FW_SIG0_ADDR-3) == SIG_BYTE3)
    {
        user_app_ready = 1;
        device_mode = APP_MODE;
    }

    if (
#ifdef BL_OVERRIDE_PIN
            (!BL_Override_Pin) ||
#endif
            (((RSTSRC & PORSF) == 0) && (RSTSRC & FERROR)))
    {
        device_mode = BOOTLOADER_MODE;
    }

    if (device_mode == APP_MODE)
    {
        // If not in BL Override, jump to application
        START_APPLICATION();
    }

    //-------------------------------------------
    // ** BL Mode ** Initialize MCU and Variables
    //-------------------------------------------
    Device_Init();

    //-------------------------------------------
    // Main Loop
    //-------------------------------------------
    while(1)
    {
        uart_receive();

        switch(rx_buf[1])
        {
        case 0x08:      // 诊断
            Diagnose();
            break;

        case 0x10:      // 写多个RW-word
            index = *(U16 *)&rx_buf[2] - TGT_BUF_START_ADDR;
            count = *(U16 *)&rx_buf[4];

            // 检查地址和数量的正确性
            if (index >= TGT_FLASH_PAGE_SIZE >> 1
                    || index + count > TGT_FLASH_PAGE_SIZE >> 1)
                Exception_Response(ILLEGAL_DATA_ADDRESS);
            else if (rx_buf[6] != count << 1)
                Exception_Response(ILLEGAL_DATA_VALUE);
            else
            {
                count <<= 1;    // word => byte
                index <<= 1;
                dst = Page_Buf + index;
                src = &rx_buf[7];
                while(count--)
                {
                    *dst++ = *src++;
                    *dst++ = *src++;
                }
                rx_len = 6;
                Response();
            }
            break;

        case 0x41:      // 读取程序Bootloader信息
#ifdef CODE_BANK
            switchbank(3);
#endif
            dst = &rx_buf[2];
            *dst++ = TGT_BL_FW_INFOBLOCK_LENGTH;
            for(n = 0; n < TGT_BL_FW_INFOBLOCK_LENGTH; ++n)
                *dst++ = TGT_BL_InfoBlock[n];
            rx_len = TGT_BL_FW_INFOBLOCK_LENGTH + 3;
            Response();
            break;

        case 0x42:      // 擦除FLASH页
            Flash_Key0 = rx_buf[6];
            Flash_Key1 = rx_buf[7];
            addr = *(U32*)&rx_buf[2];
            rx_len = 6;
            Response();
            TGT_Erase_Page(addr);
            Flash_Key0 = 0;
            Flash_Key1 = 0;
            break;

        case 0x43:      // 读取缓冲页CRC
            *(U16*)&rx_buf[2] = Get_Buf_CRC(Page_Buf, TGT_FLASH_PAGE_SIZE);
            rx_len = 4;
            Response();
            break;

        case 0x44:      // 写入FLASH页
            Flash_Key0 = rx_buf[6];
            Flash_Key1 = rx_buf[7];
            addr = *(U32*)&rx_buf[2];
            rx_len = 6;
            Response();
            TGT_Write_Flash(Page_Buf, addr);
            Flash_Key0 = 0;
            Flash_Key1 = 0;
            break;

        default:        // 不支持的指令代码
            Exception_Response(ILLEGAL_FUNCTION);
            break;
        }
    }
}
